[Android6.0][RK3399] 双屏异显代码实现流程分析(二)

Patch Code

Date: Fri, 09 Dec 2016 10:53:11 +0800
Subject: [PATCH] video: rockchip: fb: add support dual lcd
Change-Id: I246f8e7d725d26abf2555d3077dd87da72920731
Signed-off-by: Huang Jiachai < ××× >

dtsi

rk3399-android.dtsi

1
2
3
4
5
6
7
8
9
10
11
12
diff --git a/arch/arm64/boot/dts/rockchip/rk3399-android.dtsi b/arch/arm64/boot/dts/rockchip/rk3399-android.dtsi
index a009537..05a8377 100644
--- a/arch/arm64/boot/dts/rockchip/rk3399-android.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3399-android.dtsi
@@ -287,7 +287,7 @@
status = "okay";
compatible = "rockchip,rk-fb";
rockchip,disp-mode = <DUAL>;
- rockchip,uboot-logo-on = <1>;
+ rockchip,uboot-logo-on = <0>;
memory-region = <&rockchip_logo>;
};

rk3399-evb-rev3-android.dts

在 rk_screen 中默认只有一个 screen0, 用于填充 primary screen 的 timing
现在需要添加 screen1,用于填充 extend screen 的 timing

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
diff --git a/arch/arm64/boot/dts/rockchip/rk3399-evb-rev3-android.dts b/arch/arm64/boot/dts/rockchip/rk3399-evb-rev3-android.dts
index 3b3ff7c..3653205 100644
--- a/arch/arm64/boot/dts/rockchip/rk3399-evb-rev3-android.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3399-evb-rev3-android.dts
@@ -51,18 +51,55 @@
};

&rk_screen {
- #include <dt-bindings/display/screen-timing/lcd-tv080wum-nl0-mipi.dtsi>
+ status = "okay";
+ screen0 {
+ screen_prop = <PRMRY>;
+ native-mode = <DEFAULT_MODE>;
+ power_ctr {
+ lcd_en0: lcd-en {
+ rockchip,power_type = <GPIO>;
+ gpios = <&gpio1 13 GPIO_ACTIVE_HIGH>;
+ rockchip,delay = <10>;
+ };
+ /* lcd_cs {
+ rockchip,power_type = <GPIO>;
+ gpios = <&gpio7 GPIO_A4 GPIO_ACTIVE_HIGH>;
+ rockchip,delay = <10>;
+ }; */
+ };
+ #include <dt-bindings/display/screen-timing/lcd-tv080wum-nl0-mipi.dtsi>
+ //#include <dt-bindings/display/screen-timing/lcd-F402.dtsi>
+ };
+ screen1 {
+ screen_prop = <EXTEND>;
+ native-mode = <DEFAULT_MODE>;
+ power_ctr {
+ /* cd_en1: lcd-en {
+ rockchip,power_type = <GPIO>;
+ gpios = <&gpio1 13 GPIO_ACTIVE_HIGH>;
+ rockchip,delay = <10>;
+ };*/
+ /* lcd_cs {
+ rockchip,power_type = <GPIO>;
+ gpios = <&gpio7 GPIO_A4 GPIO_ACTIVE_HIGH>;
+ rockchip,delay = <10>;
+ }; */
+ };
+ #include <dt-bindings/display/screen-timing/lcd-F402.dtsi>
+ //#include <dt-bindings/display/screen-timing/lcd-tv080wum-nl0-mipi.dtsi>
+ //#include "lcd-box.dtsi"
+ };
};

&vopb_rk_fb {
status = "okay";
power_ctr: power_ctr {
rockchip,debug = <0>;
- lcd_en: lcd-en {
+ /* lcd_en: lcd-en {
rockchip,power_type = <GPIO>;
gpios = <&gpio1 13 GPIO_ACTIVE_HIGH>;
rockchip,delay = <10>;
- };
+ }; */

/*lcd_cs: lcd-cs {
rockchip,power_type = <GPIO>;
@@ -80,14 +117,23 @@

&vopl_rk_fb {
status = "okay";
+ rockchip,uboot-logo-on = <0>;
};

//设置 mipi 通道的为主屏, eDP 的为副屏

&mipi0_rk_fb {
status = "okay";
+ prop = <PRMRY>;
+ //prop = <EXTEND>;
+};
+
+&edp_rk_fb {
+ status = "okay";
+ prop = <EXTEND>;
+ //prop = <PRMRY>;
};

&hdmi_rk_fb {
- status = "okay";
+ status = "disabled";
rockchip,hdmi_video_source = <DISPLAY_SOURCE_LCDC1>;
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
diff --git a/arch/arm64/boot/dts/rockchip/rk3399-evb.dtsi b/arch/arm64/boot/dts/rockchip/rk3399-evb.dtsi
index b3c7141..b72ce6c 100644
--- a/arch/arm64/boot/dts/rockchip/rk3399-evb.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3399-evb.dtsi
@@ -101,7 +101,7 @@
232 233 234 235 236 237 238 239
240 241 242 243 244 245 246 247
248 249 250 251 252 253 254 255>;
- default-brightness-level = <200>;
+ default-brightness-level = <128>;
};

clkin_gmac: external-gmac-clock {
@@ -370,7 +370,7 @@
};

&i2c4 {
- status = "okay";
+ status = "disabled";
i2c-scl-rising-time-ns = <600>;
i2c-scl-falling-time-ns = <20>;

lcdc 控制器

rk322x_lcdc.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
diff --git a/drivers/video/rockchip/lcdc/rk322x_lcdc.c b/drivers/video/rockchip/lcdc/rk322x_lcdc.c
index 93c996a..d6bdff3 100644
--- a/drivers/video/rockchip/lcdc/rk322x_lcdc.c
+++ b/drivers/video/rockchip/lcdc/rk322x_lcdc.c
@@ -5252,6 +5252,10 @@

rk322x_pdev = pdev;

+ if (dev_drv->cur_screen->type != SCREEN_HDMI &&
+ dev_drv->cur_screen->type != SCREEN_TVOUT)
+ dev_drv->hot_plug_state = 1;
+
if (dev_drv->cur_screen->refresh_mode == SCREEN_CMD_MODE) {
te_pin = of_get_named_gpio_flags(np, "te-gpio", 0, NULL);
if (IS_ERR_VALUE(te_pin)) {

rk_fb.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
diff --git a/drivers/video/rockchip/rk_fb.c b/drivers/video/rockchip/rk_fb.c
index 25563a4..80db2e2 100644
--- a/drivers/video/rockchip/rk_fb.c
+++ b/drivers/video/rockchip/rk_fb.c
@@ -73,9 +73,8 @@
extern phys_addr_t uboot_logo_base;
extern phys_addr_t uboot_logo_size;
extern phys_addr_t uboot_logo_offset;
-static struct rk_fb_trsm_ops *trsm_lvds_ops;
-static struct rk_fb_trsm_ops *trsm_edp_ops;
-static struct rk_fb_trsm_ops *trsm_mipi_ops;
+static struct rk_fb_trsm_ops *trsm_prmry_ops;
+static struct rk_fb_trsm_ops *trsm_extend_ops;
static int uboot_logo_on;

static int rk_fb_debug_lvl;
@@ -115,26 +114,13 @@

int rk_fb_trsm_ops_register(struct rk_fb_trsm_ops *ops, int type)
{
- switch (type) {
- case SCREEN_RGB:
- case SCREEN_LVDS:
- case SCREEN_DUAL_LVDS:
- case SCREEN_LVDS_10BIT:
- case SCREEN_DUAL_LVDS_10BIT:
- trsm_lvds_ops = ops;
- break;
- case SCREEN_EDP:
- trsm_edp_ops = ops;
- break;
- case SCREEN_MIPI:
- case SCREEN_DUAL_MIPI:
- trsm_mipi_ops = ops;
- break;
- default:
- pr_warn("%s: unsupported transmitter: %d!\n",
- __func__, type);
- break;
- }
+ if (type == PRMRY)
+ trsm_prmry_ops = ops;
+ else if (type == EXTEND)
+ trsm_extend_ops = ops;
+ else
+ pr_err("%s, type:%d\n", __func__, type);
+
return 0;
}

@@ -142,27 +128,12 @@
{
struct rk_fb_trsm_ops *ops;

- switch (type) {
- case SCREEN_RGB:
- case SCREEN_LVDS:
- case SCREEN_DUAL_LVDS:
- case SCREEN_LVDS_10BIT:
- case SCREEN_DUAL_LVDS_10BIT:
- ops = trsm_lvds_ops;
- break;
- case SCREEN_EDP:
- ops = trsm_edp_ops;
- break;
- case SCREEN_MIPI:
- case SCREEN_DUAL_MIPI:
- ops = trsm_mipi_ops;
- break;
- default:
- ops = NULL;
- pr_warn("%s: unsupported transmitter: %d!\n",
- __func__, type);
- break;
- }
+ if (type == PRMRY)
+ ops = trsm_prmry_ops;
+ else if (type == EXTEND)
+ ops = trsm_extend_ops;
+ else
+ pr_err("%s, type:%d\n", __func__, type);
return ops;
}

@@ -317,10 +288,10 @@
/*
* rk display power control parse from dts
*/
-int rk_disp_pwr_ctr_parse_dt(struct rk_lcdc_driver *dev_drv)
+int rk_disp_pwr_ctr_parse_dt(struct device_node *np,
+ struct rk_screen *rk_screen)
{
- struct device_node *root = of_get_child_by_name(dev_drv->dev->of_node,
- "power_ctr");
+ struct device_node *root = of_get_child_by_name(np, "power_ctr");
struct device_node *child;
struct rk_disp_pwr_ctr_list *pwr_ctr;
struct list_head *pos;
@@ -329,10 +300,10 @@
u32 debug = 0;
int ret;

- INIT_LIST_HEAD(&dev_drv->pwrlist_head);
+ INIT_LIST_HEAD(rk_screen->pwrlist_head);
if (!root) {
- dev_err(dev_drv->dev, "can't find power_ctr node for lcdc%d\n",
- dev_drv->id);
+ dev_err(rk_screen->dev, "can't find power_ctr node for lcdc%d\n",
+ rk_screen->lcdc_id);
return -ENODEV;
}

@@ -347,7 +318,7 @@
pwr_ctr->pwr_ctr.type = GPIO;
pwr_ctr->pwr_ctr.gpio = of_get_gpio_flags(child, 0, &flags);
if (!gpio_is_valid(pwr_ctr->pwr_ctr.gpio)) {
- dev_err(dev_drv->dev, "%s ivalid gpio\n",
+ dev_err(rk_screen->dev, "%s ivalid gpio\n",
child->name);
return -EINVAL;
}
@@ -355,7 +326,7 @@
ret = gpio_request(pwr_ctr->pwr_ctr.gpio,
child->name);
if (ret) {
- dev_err(dev_drv->dev,
+ dev_err(rk_screen->dev,
"request %s gpio fail:%d\n",
child->name, ret);
}
@@ -364,9 +335,9 @@
pwr_ctr->pwr_ctr.type = REGULATOR;
pwr_ctr->pwr_ctr.rgl_name = NULL;
ret = of_property_read_string(child, "rockchip,regulator_name",
- &(pwr_ctr->pwr_ctr.rgl_name));
+ &(pwr_ctr->pwr_ctr.rgl_name));
if (ret || IS_ERR_OR_NULL(pwr_ctr->pwr_ctr.rgl_name))
- dev_err(dev_drv->dev, "get regulator name failed!\n");
+ dev_err(rk_screen->dev, "get regulator name failed!\n");
if (!of_property_read_u32(child, "rockchip,regulator_voltage", &val))
pwr_ctr->pwr_ctr.volt = val;
else
@@ -378,29 +349,30 @@
pwr_ctr->pwr_ctr.delay = val;
else
pwr_ctr->pwr_ctr.delay = 0;
- list_add_tail(&pwr_ctr->list, &dev_drv->pwrlist_head);
+ list_add_tail(&pwr_ctr->list, rk_screen->pwrlist_head);
}

of_property_read_u32(root, "rockchip,debug", &debug);

if (debug) {
- list_for_each(pos, &dev_drv->pwrlist_head) {
+ list_for_each(pos, rk_screen->pwrlist_head) {
pwr_ctr = list_entry(pos, struct rk_disp_pwr_ctr_list,
list);
- pr_info("pwr_ctr_name:%s\n"
- "pwr_type:%s\n"
- "gpio:%d\n"
- "atv_val:%d\n"
- "delay:%d\n\n",
- pwr_ctr->pwr_ctr.name,
- (pwr_ctr->pwr_ctr.type == GPIO) ? "gpio" : "regulator",
- pwr_ctr->pwr_ctr.gpio,
- pwr_ctr->pwr_ctr.atv_val,
- pwr_ctr->pwr_ctr.delay);
+ printk(KERN_INFO "pwr_ctr_name:%s\n"
+ "pwr_type:%s\n"
+ "gpio:%d\n"
+ "atv_val:%d\n"
+ "delay:%d\n\n",
+ pwr_ctr->pwr_ctr.name,
+ (pwr_ctr->pwr_ctr.type == GPIO) ? "gpio" : "regulator",
+ pwr_ctr->pwr_ctr.gpio,
+ pwr_ctr->pwr_ctr.atv_val,
+ pwr_ctr->pwr_ctr.delay);
}
}

return 0;
+
}

int rk_disp_pwr_enable(struct rk_lcdc_driver *dev_drv)
@@ -411,9 +383,14 @@
struct regulator *regulator_lcd = NULL;
int count = 10;

- if (list_empty(&dev_drv->pwrlist_head))
+ if (!dev_drv->cur_screen->pwrlist_head) {
+ pr_info("error: %s, lcdc%d screen pwrlist null\n",
+ __func__, dev_drv->id);
return 0;
- list_for_each(pos, &dev_drv->pwrlist_head) {
+ }
+ if (list_empty(dev_drv->cur_screen->pwrlist_head))
+ return 0;
+ list_for_each(pos, dev_drv->cur_screen->pwrlist_head) {
pwr_ctr_list = list_entry(pos, struct rk_disp_pwr_ctr_list,
list);
pwr_ctr = &pwr_ctr_list->pwr_ctr;
@@ -422,8 +399,7 @@
mdelay(pwr_ctr->delay);
} else if (pwr_ctr->type == REGULATOR) {
if (pwr_ctr->rgl_name)
- regulator_lcd =
- regulator_get(NULL, pwr_ctr->rgl_name);
+ regulator_lcd = regulator_get(NULL, pwr_ctr->rgl_name);
if (regulator_lcd == NULL) {
dev_err(dev_drv->dev,
"%s: regulator get failed,regulator name:%s\n",
@@ -456,9 +432,14 @@
struct regulator *regulator_lcd = NULL;
int count = 10;

- if (list_empty(&dev_drv->pwrlist_head))
+ if (!dev_drv->cur_screen->pwrlist_head) {
+ pr_info("error: %s, lcdc%d screen pwrlist null\n",
+ __func__, dev_drv->id);
return 0;
- list_for_each(pos, &dev_drv->pwrlist_head) {
+ }
+ if (list_empty(dev_drv->cur_screen->pwrlist_head))
+ return 0;
+ list_for_each(pos, dev_drv->cur_screen->pwrlist_head) {
pwr_ctr_list = list_entry(pos, struct rk_disp_pwr_ctr_list,
list);
pwr_ctr = &pwr_ctr_list->pwr_ctr;
@@ -474,8 +455,7 @@
continue;
}
while (regulator_is_enabled(regulator_lcd) > 0) {
- if (regulator_disable(regulator_lcd) == 0 ||
- count == 0)
+ if (regulator_disable(regulator_lcd) == 0 || count == 0)
break;
else
dev_err(dev_drv->dev,
@@ -530,6 +510,8 @@
screen->pin_den = 1;
else
screen->pin_den = 0;
+ printk("hjc>>>prop:%d, x:%d, y:%d, dclk:%d\n", screen->prop,
+ screen->mode.xres, screen->mode.yres, screen->mode.pixclock);

return 0;
}
@@ -544,7 +526,7 @@
pr_err("parse display timing err\n");
return -EINVAL;
}
- dt = display_timings_get(disp_timing, disp_timing->native_mode);
+ dt = display_timings_get(disp_timing, screen->native_mode);
rk_fb_video_mode_from_timing(dt, screen);

return 0;
@@ -3942,7 +3924,8 @@
win = dev_drv->win[win_id];

if (!strcmp(fbi->fix.id, "fb0")) {
- fb_mem_size = get_fb_size(dev_drv->reserved_fb);
+ fb_mem_size = get_fb_size(dev_drv->reserved_fb,
+ dev_drv->cur_screen);
#if defined(CONFIG_ION_ROCKCHIP)
if (rk_fb_alloc_buffer_by_ion(fbi, win, fb_mem_size) < 0)
return -ENOMEM;
@@ -3963,8 +3946,7 @@
if (dev_drv->prop == EXTEND && dev_drv->iommu_enabled) {
struct rk_lcdc_driver *dev_drv_prmry;
int win_id_prmry;
-
- fb_mem_size = get_fb_size(dev_drv->reserved_fb);
+ fb_mem_size = get_fb_size(dev_drv->reserved_fb, dev_drv->cur_screen);
#if defined(CONFIG_ION_ROCKCHIP)
dev_drv_prmry = rk_get_prmry_lcdc_drv();
if (dev_drv_prmry == NULL)
@@ -4129,14 +4111,9 @@
dev_drv->area_support[i] = 1;
if (dev_drv->ops->area_support_num)
dev_drv->ops->area_support_num(dev_drv, dev_drv->area_support);
- rk_disp_pwr_ctr_parse_dt(dev_drv);
- if (dev_drv->prop == PRMRY) {
- rk_fb_set_prmry_screen(screen);
- rk_fb_get_prmry_screen(screen);
- }
- dev_drv->trsm_ops = rk_fb_trsm_ops_get(screen->type);
- if (dev_drv->prop != PRMRY)
- rk_fb_get_extern_screen(screen);
+ rk_fb_set_screen(screen, dev_drv->prop);
+ rk_fb_get_screen(screen, dev_drv->prop);
+ dev_drv->trsm_ops = rk_fb_trsm_ops_get(dev_drv->prop);
dev_drv->output_color = screen->color_mode;

return 0;
@@ -4511,15 +4488,24 @@
struct fb_info *extend_fbi = rk_fb->fb[dev_drv->fb_index_base];

extend_fbi->var.pixclock = rk_fb->fb[0]->var.pixclock;
- if (rk_fb->disp_mode == DUAL_LCD) {
- extend_fbi->fbops->fb_open(extend_fbi, 1);
- if (dev_drv->iommu_enabled) {
- if (dev_drv->mmu_dev)
- rockchip_iovmm_set_fault_handler(dev_drv->dev,
- rk_fb_sysmmu_fault_handler);
- }
- rk_fb_alloc_buffer(extend_fbi);
+ extend_fbi->var.xres_virtual = rk_fb->fb[0]->var.xres_virtual;
+ extend_fbi->var.yres_virtual = rk_fb->fb[0]->var.yres_virtual;
+ extend_fbi->var.xres = rk_fb->fb[0]->var.xres;
+ extend_fbi->var.yres = rk_fb->fb[0]->var.yres;
+ extend_fbi->fbops->fb_open(extend_fbi, 1);
+ if (dev_drv->iommu_enabled) {
+ if (dev_drv->mmu_dev)
+ rockchip_iovmm_set_fault_handler(dev_drv->dev,
+ rk_fb_sysmmu_fault_handler);
+ if (dev_drv->ops->mmu_en)
+ dev_drv->ops->mmu_en(dev_drv);
}
+ rk_fb_alloc_buffer(extend_fbi);
+ //if (rk_fb->disp_mode == DUAL_LCD) {
+ extend_fbi->fbops->fb_set_par(extend_fbi);
+ extend_fbi->fbops->fb_pan_display(&extend_fbi->var,
+ extend_fbi);
+ //}
}
#endif
return 0;

timing 初始化

rk_screen.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
diff --git a/drivers/video/rockchip/screen/rk_screen.c b/drivers/video/rockchip/screen/rk_screen.c
index 3a4e6c3..7473e5f 100644
--- a/drivers/video/rockchip/screen/rk_screen.c
+++ b/drivers/video/rockchip/screen/rk_screen.c
@@ -4,57 +4,102 @@
#include "lcd.h"
#include "../hdmi/rockchip-hdmi.h"

-static struct rk_screen *rk_screen;
+static struct rk_screen *prmry_screen;
+static struct rk_screen *extend_screen;
+
+static void rk_screen_info_error(struct rk_screen *screen, int prop)
+{
+ pr_err(">>>>>>>>>>>>>>>>>>>>error<<<<<<<<<<<<<<<<<<<<\n");
+ pr_err(">>please init %s screen info in dtsi file<<\n",
+ (prop == PRMRY) ? "prmry" : "extend");
+ pr_err(">>>>>>>>>>>>>>>>>>>>error<<<<<<<<<<<<<<<<<<<<\n");
+}

int rk_fb_get_extern_screen(struct rk_screen *screen)
{
- if (unlikely(!rk_screen) || unlikely(!screen))
+ if (unlikely(!extend_screen) || unlikely(!screen))
return -1;
-
- memcpy(screen, rk_screen, sizeof(struct rk_screen));
+ memcpy(screen, extend_screen, sizeof(struct rk_screen));
screen->dsp_lut = NULL;
screen->cabc_lut = NULL;
- screen->type = SCREEN_NULL;
-
return 0;
}

-int rk_fb_get_prmry_screen(struct rk_screen *screen)
+int rk_fb_get_prmry_screen(struct rk_screen *screen)
{
- if (unlikely(!rk_screen) || unlikely(!screen))
+ if (unlikely(!prmry_screen) || unlikely(!screen))
return -1;

- memcpy(screen, rk_screen, sizeof(struct rk_screen));
+ memcpy(screen, prmry_screen, sizeof(struct rk_screen));
return 0;
}

-int rk_fb_set_prmry_screen(struct rk_screen *screen)
+int rk_fb_get_screen(struct rk_screen *screen, int prop)
{
- if (unlikely(!rk_screen) || unlikely(!screen))
+ struct rk_screen *cur_screen = NULL;
+ if (unlikely(!screen))
return -1;

- rk_screen->lcdc_id = screen->lcdc_id;
- rk_screen->screen_id = screen->screen_id;
- rk_screen->x_mirror = screen->x_mirror;
- rk_screen->y_mirror = screen->y_mirror;
- rk_screen->overscan.left = screen->overscan.left;
- rk_screen->overscan.top = screen->overscan.left;
- rk_screen->overscan.right = screen->overscan.left;
- rk_screen->overscan.bottom = screen->overscan.left;
+ if (prop == PRMRY) {
+ if (unlikely(!prmry_screen)) {
+ rk_screen_info_error(screen, prop);
+ return -1;
+ }
+ cur_screen = prmry_screen;
+ } else {
+ if (unlikely(!extend_screen)) {
+ rk_screen_info_error(screen, prop);
+ return -1;
+ }
+ cur_screen = extend_screen;
+ }
+ memcpy(screen, cur_screen, sizeof(struct rk_screen));
return 0;
}

-size_t get_fb_size(u8 reserved_fb)
+int rk_fb_set_screen(struct rk_screen *screen, int prop)
+{
+ struct rk_screen *cur_screen = NULL;
+
+ if (unlikely(!screen))
+ return -1;
+ if (prop == PRMRY) {
+ if (unlikely(!prmry_screen)) {
+ rk_screen_info_error(screen, prop);
+ return -1;
+ }
+ cur_screen = prmry_screen;
+ } else {
+ if (unlikely(!extend_screen)) {
+ rk_screen_info_error(screen, prop);
+ return -1;
+ }
+ cur_screen = extend_screen;
+ }
+
+ cur_screen->lcdc_id = screen->lcdc_id;
+ cur_screen->screen_id = screen->screen_id;
+ cur_screen->x_mirror = screen->x_mirror;
+ cur_screen->y_mirror = screen->y_mirror;
+ cur_screen->overscan.left = screen->overscan.left;
+ cur_screen->overscan.top = screen->overscan.left;
+ cur_screen->overscan.right = screen->overscan.left;
+ cur_screen->overscan.bottom = screen->overscan.left;
+
+ return 0;
+}
+
+size_t get_fb_size(u8 reserved_fb, struct rk_screen *screen)
{
size_t size = 0;
u32 xres = 0;
u32 yres = 0;

- if (unlikely(!rk_screen))
+ if (unlikely(!screen))
return 0;

- xres = rk_screen->mode.xres;
- yres = rk_screen->mode.yres;
+ xres = screen->mode.xres;
+ yres = screen->mode.yres;

/* align as 64 bytes(16*4) in an odd number of times */
xres = ALIGN_64BYTE_ODD_TIMES(xres, ALIGN_PIXEL_64BYTE_RGB8888);
@@ -73,22 +118,51 @@
static int rk_screen_probe(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
- int ret;
+ struct device_node *screen_np;
+ struct rk_screen *rk_screen;
+ int ret, screen_prop;

if (!np) {
dev_err(&pdev->dev, "Missing device tree node.\n");
return -EINVAL;
}
- rk_screen = devm_kzalloc(&pdev->dev,
- sizeof(struct rk_screen), GFP_KERNEL);
- if (!rk_screen) {
- dev_err(&pdev->dev, "kmalloc for rk screen fail!");
- return -ENOMEM;
+
+ for_each_child_of_node(np, screen_np) {
+ rk_screen = devm_kzalloc(&pdev->dev,
+ sizeof(struct rk_screen), GFP_KERNEL);
+ if (!rk_screen) {
+ dev_err(&pdev->dev, "kmalloc for rk screen fail!");
+ return -ENOMEM;
+ }
+ rk_screen->pwrlist_head = devm_kzalloc(&pdev->dev,
+ sizeof(struct list_head), GFP_KERNEL);
+ if (!rk_screen->pwrlist_head) {
+ dev_err(&pdev->dev, "kmalloc for rk_screen pwrlist_head fail!");
+ return -ENOMEM;
+ }
+ of_property_read_u32(screen_np, "screen_prop", &screen_prop);
+ if (screen_prop == PRMRY)
+ prmry_screen = rk_screen;
+ else if (screen_prop == EXTEND)
+ extend_screen = rk_screen;
+ else
+ dev_err(&pdev->dev, "unknow screen prop: %d\n",
+ screen_prop);
+ rk_screen->prop = screen_prop;
+ of_property_read_u32(screen_np, "native-mode", &rk_screen->native_mode);
+ rk_screen->dev = &pdev->dev;
+ ret = rk_fb_prase_timing_dt(screen_np, rk_screen);
+ pr_info("%s screen timing parse %s\n",
+ (screen_prop == PRMRY) ? "prmry" : "extend",
+ ret ? "failed" : "success");
+ ret = rk_disp_pwr_ctr_parse_dt(screen_np, rk_screen);
+ pr_info("%s screen power ctrl parse %s\n",
+ (screen_prop == PRMRY) ? "prmry" : "extend",
+ ret ? "failed" : "success");
}
- ret = rk_fb_prase_timing_dt(np, rk_screen);
- dev_info(&pdev->dev, "rockchip screen probe %s\n",
- ret ? "failed" : "success");
- return ret;
+
+ dev_info(&pdev->dev, "rockchip screen probe success\n");
+ return 0;
}

static const struct of_device_id rk_screen_dt_ids[] = {

rk32_dp.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
diff --git a/drivers/video/rockchip/transmitter/rk32_dp.c b/drivers/video/rockchip/transmitter/rk32_dp.c
index 6d386bc..0bffdb0 100755
--- a/drivers/video/rockchip/transmitter/rk32_dp.c
+++ b/drivers/video/rockchip/transmitter/rk32_dp.c
@@ -129,7 +129,7 @@
struct rk_screen *screen = &edp->screen;
u32 val = 0;

- rk_fb_get_prmry_screen(screen);
+ rk_fb_get_screen(screen, edp->prop);

if (cpu_is_rk3288()) {
if (screen->lcdc_id == 1) /*select lcdc*/
@@ -1734,17 +1734,21 @@
struct resource *res;
struct device_node *np = pdev->dev.of_node;
int ret;
+ int prop;

if (!np) {
dev_err(&pdev->dev, "Missing device tree node.\n");
return -EINVAL;
}
+ of_property_read_u32(np, "prop", &prop);
+ pr_info("Use EDP as %s screen\n", (prop == PRMRY) ? "prmry" : "extend");

edp = devm_kzalloc(&pdev->dev, sizeof(struct rk32_edp), GFP_KERNEL);
if (!edp) {
dev_err(&pdev->dev, "no memory for state\n");
return -ENOMEM;
}
+ edp->prop = prop;
edp->dev = &pdev->dev;
edp->video_info.h_sync_polarity = 0;
edp->video_info.v_sync_polarity = 0;
@@ -1756,7 +1760,7 @@

edp->video_info.link_rate = LINK_RATE_1_62GBPS;
edp->video_info.lane_count = LANE_CNT4;
- rk_fb_get_prmry_screen(&edp->screen);
+ rk_fb_get_screen(&edp->screen, prop);
if (edp->screen.type != SCREEN_EDP) {
dev_err(&pdev->dev, "screen is not edp!\n");
return -EINVAL;
@@ -1852,7 +1856,7 @@
pm_runtime_get_sync(&pdev->dev);

rk32_edp = edp;
- rk_fb_trsm_ops_register(&trsm_edp_ops, SCREEN_EDP);
+ rk_fb_trsm_ops_register(&trsm_edp_ops, prop);
#if defined(CONFIG_DEBUG_FS)
edp->debugfs_dir = debugfs_create_dir("edp", NULL);
if (IS_ERR(edp->debugfs_dir)) {
diff --git a/drivers/video/rockchip/transmitter/rk32_dp.h b/drivers/video/rockchip/transmitter/rk32_dp.h
index 2dc41c6..fda0de2 100755
--- a/drivers/video/rockchip/transmitter/rk32_dp.h
+++ b/drivers/video/rockchip/transmitter/rk32_dp.h
@@ -571,6 +571,7 @@
bool edp_en;
int soctype;
struct dentry *debugfs_dir;
+ int prop;
};

rk32_mipi_dsi.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
diff --git a/drivers/video/rockchip/transmitter/rk32_mipi_dsi.c b/drivers/video/rockchip/transmitter/rk32_mipi_dsi.c
index 741fdb5..ed68d85 100644
--- a/drivers/video/rockchip/transmitter/rk32_mipi_dsi.c
+++ b/drivers/video/rockchip/transmitter/rk32_mipi_dsi.c
@@ -1609,7 +1609,7 @@
pm_runtime_get_sync(&dsi0->pdev->dev);
#endif
opt_mode = dsi0->screen.refresh_mode;
- rk_fb_get_prmry_screen(dsi0->screen.screen);
+ rk_fb_get_screen(dsi0->screen.screen, dsi0->prop);
dsi0->screen.lcdc_id = dsi0->screen.screen->lcdc_id;
rk32_init_phy_mode(dsi0->screen.lcdc_id);

@@ -1875,7 +1875,7 @@
static int rk32_mipi_dsi_probe(struct platform_device *pdev)
{
int ret = 0;
- static int id;
+ static int id, prop;
struct dsi *dsi;
struct mipi_dsi_ops *ops;
struct rk_screen *screen;
@@ -1890,7 +1890,8 @@
return -ENODEV;
}
data = of_id->data;
-
+ of_property_read_u32(np, "prop", &prop);
+ pr_info("Use mipi as %s screen\n", (prop == PRMRY) ? "prmry" : "extend");
dsi = devm_kzalloc(&pdev->dev, sizeof(struct dsi), GFP_KERNEL);
if (!dsi) {
dev_err(&pdev->dev, "request struct dsi fail!\n");
@@ -1997,8 +1998,8 @@
dev_err(&pdev->dev, "request struct rk_screen fail!\n");
return -1;
}
- rk_fb_get_prmry_screen(screen);
-
+ rk_fb_get_screen(screen, prop);
+ dsi->prop = prop;
dsi->pdev = pdev;
ops = &dsi->ops;
ops->dsi = dsi;
@@ -2056,7 +2057,7 @@
if(!support_uboot_display())
rk32_init_phy_mode(dsi_screen->lcdc_id);
*/
- rk_fb_trsm_ops_register(&trsm_dsi_ops, SCREEN_MIPI);
+ rk_fb_trsm_ops_register(&trsm_dsi_ops, prop);
#ifdef MIPI_DSI_REGISTER_IO
debugfs_create_file("mipidsi0", S_IFREG | S_IRUGO, dsi->debugfs_dir, dsi,
&reg_proc_fops);

rk32_mipi_dsi.h

1
2
3
4
5
6
7
8
9
10
11
12
diff --git a/drivers/video/rockchip/transmitter/rk32_mipi_dsi.h b/drivers/video/rockchip/transmitter/rk32_mipi_dsi.h
index f568254..473db82 100644
--- a/drivers/video/rockchip/transmitter/rk32_mipi_dsi.h
+++ b/drivers/video/rockchip/transmitter/rk32_mipi_dsi.h
@@ -307,6 +307,7 @@
struct dsi {
u8 dsi_id;
u8 lcdc_id;
+ int prop;
u8 vid;
u8 clk_on;
struct regmap *grf_base;

rk_fb.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
diff --git a/include/dt-bindings/display/rk_fb.h b/include/dt-bindings/display/rk_fb.h
index 81c9855..ae7241d 100755
--- a/include/dt-bindings/display/rk_fb.h
+++ b/include/dt-bindings/display/rk_fb.h
@@ -14,6 +14,13 @@
#define DUAL 2
#define DUAL_LCD 3

+#define DEFAULT_MODE 0
+#define HDMI_720P 0
+#define HDMI_1080P 1
+#define HDMI_2160P 2
+#define NTSC_CVBS 3
+#define PAL_CVBS 4
+
#define DEFAULT_MODE 0
#define ONE_VOP_DUAL_MIPI_HOR_SCAN 1
#define ONE_VOP_DUAL_MIPI_VER_SCAN 2

lcd 的 dtsi

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
diff --git a/include/dt-bindings/display/screen-timing/lcd-F402.dtsi b/include/dt-bindings/display/screen-timing/lcd-F402.dtsi
index a3ad25f..abe178f 100644
--- a/include/dt-bindings/display/screen-timing/lcd-F402.dtsi
+++ b/include/dt-bindings/display/screen-timing/lcd-F402.dtsi
@@ -4,9 +4,9 @@
*/


-disp_timings: display-timings {
- native-mode = <&timing0>;
- timing0: timing0 {
+display-timings {
+ native-mode = <&f402>;
+ f402: timing0 {
screen-type = <SCREEN_EDP>;
out-face = <OUT_P666>;
clock-frequency = <205000000>;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
diff --git a/include/dt-bindings/display/screen-timing/lcd-box.dtsi b/include/dt-bindings/display/screen-timing/lcd-box.dtsi
index 2109a89..20e2a21 100644
--- a/include/dt-bindings/display/screen-timing/lcd-box.dtsi
+++ b/include/dt-bindings/display/screen-timing/lcd-box.dtsi
@@ -3,36 +3,9 @@
*
*/

- disp_power_ctr: power_ctr {
- /* rockchip,debug = <0>;
- lcd_en:lcd_en {
- rockchip,power_type = <GPIO>;
- gpios = <&gpio0 GPIO_B0 GPIO_ACTIVE_HIGH>;
- rockchip,delay = <10>;
- };
-
- bl_en:bl_en {
- rockchip,power_type = <GPIO>;
- gpios = <&gpio0 GPIO_A2 GPIO_ACTIVE_HIGH>;
- rockchip,delay = <10>;
- };
-
- bl_ctr:bl_ctr {
- rockchip,power_type = <GPIO>;
- gpios = <&gpio3 GPIO_D6 GPIO_ACTIVE_HIGH>;
- rockchip,delay = <10>;
- };
-
- lcd_rst:lcd_rst {
- rockchip,power_type = <REGULATOR>;
- rockchip,delay = <5>;
- };*/
-
-};
-
-disp_timings: display-timings {
- native-mode = <&timing0>;
- timing0: timing0 {
+display-timings {
+ native-mode = <&hdmi_720p>;
+ hdmi_720p: timing0 {
screen-type = <SCREEN_RGB>;
out-face = <OUT_P888>;
color-mode = <COLOR_YCBCR>;
@@ -53,7 +26,7 @@
swap-rg = <0>;
swap-gb = <0>;
};
- timing1: timing1 {
+ hdmi_1080p: timing1 {
screen-type = <SCREEN_RGB>;
out-face = <OUT_P888>;
color-mode = <COLOR_YCBCR>;
@@ -74,7 +47,7 @@
swap-rg = <0>;
swap-gb = <0>;
};
- timing2: timing2 {
+ hdmi_2160p: timing2 {
screen-type = <SCREEN_RGB>;
out-face = <OUT_P888>;
color-mode = <COLOR_YCBCR>;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
diff --git a/include/dt-bindings/display/screen-timing/lcd-tv080wum-nl0-mipi.dtsi b/include/dt-bindings/display/screen-timing/lcd-tv080wum-nl0-mipi.dtsi
index b408d65..6a203a9 100644
--- a/include/dt-bindings/display/screen-timing/lcd-tv080wum-nl0-mipi.dtsi
+++ b/include/dt-bindings/display/screen-timing/lcd-tv080wum-nl0-mipi.dtsi
@@ -84,10 +84,10 @@
*/
};

-disp_timings: display-timings {
- native-mode = <&timing0>;
+display-timings {
+ native-mode = <&tv080wum_nl0_mipi>;
compatible = "rockchip,display-timings";
- timing0: timing0 {
+ tv080wum_nl0_mipi: timing0 {
screen-type = <SCREEN_MIPI>;
lvds-format = <LVDS_8BIT_2>;
out-face = <OUT_P888>;
diff --git a/include/linux/rk_fb.h b/include/linux/rk_fb.h
index d7634a8..1130ea4 100755
--- a/include/linux/rk_fb.h
+++ b/include/linux/rk_fb.h
@@ -811,7 +811,10 @@
extern int rk_fb_get_prmry_screen( struct rk_screen *screen);
extern int rk_fb_set_prmry_screen(struct rk_screen *screen);
extern u32 rk_fb_get_prmry_screen_pixclock(void);
-extern int rk_disp_pwr_ctr_parse_dt(struct rk_lcdc_driver *dev_drv);
+extern int rk_fb_get_screen(struct rk_screen *screen, int prop);
+extern int rk_fb_set_screen(struct rk_screen *screen, int prop);
+extern int rk_disp_pwr_ctr_parse_dt(struct device_node *np,
+ struct rk_screen *rk_screen);
extern int rk_disp_pwr_enable(struct rk_lcdc_driver *dev_drv);
extern int rk_disp_pwr_disable(struct rk_lcdc_driver *dev_drv);
extern bool is_prmry_rk_lcdc_registered(void);
diff --git a/include/linux/rk_screen.h b/include/linux/rk_screen.h
index 5e5cd30..71a0d4d 100644
--- a/include/linux/rk_screen.h
+++ b/include/linux/rk_screen.h
@@ -61,13 +61,17 @@
*ft: the time need to display one frame time
*/
struct rk_screen {
- u16 type;
+ struct device *dev;
+ int prop;
u16 refresh_mode;
+ struct list_head *pwrlist_head;
+ u16 type;
u16 lvds_format;
u16 face;
u16 color_mode;
u8 lcdc_id;
u8 screen_id;
+ int native_mode;
struct fb_videomode mode;
u32 post_dsp_stx;
u32 post_dsp_sty;
@@ -145,7 +149,7 @@
};

extern void set_lcd_info(struct rk_screen *screen, struct rk29lcd_info *lcd_info);
-extern size_t get_fb_size(u8 reserved_fb);
+extern size_t get_fb_size(u8 reserved_fb, struct rk_screen *screen);

extern void set_tv_info(struct rk_screen *screen);
extern void set_hdmi_info(struct rk_screen *screen);
您的支持将鼓励我继续创作!